package org.gm.mybatis.ext.typehandler;

import java.sql.Array;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

@MappedTypes({List.class})
@MappedJdbcTypes({JdbcType.ARRAY})
public class ArrayTypeHandler extends BaseTypeHandler<List<?>> {

    private static final String TYPE_NAME_VARCHAR = "varchar";
    private static final String TYPE_NAME_INTEGER = "integer";
    private static final String TYPE_NAME_BOOLEAN = "boolean";
    private static final String TYPE_NAME_NUMERIC = "numeric";
    private static final String TYPE_NAME_BIGINT = "bigint";
    
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List<?> parameter,
            JdbcType jdbcType) throws SQLException {
    	
        String typeName = null;
        
        if(parameter.size()>0){
	    	Object subject = parameter.get(0);
	        if (subject.getClass().equals(java.lang.Integer.class)) {
	            typeName = TYPE_NAME_INTEGER;
	        } else if (subject.getClass().equals(java.lang.String.class)) {
	            typeName = TYPE_NAME_VARCHAR;
	        } else if (subject.getClass().equals(java.lang.Boolean.class)) {
	            typeName = TYPE_NAME_BOOLEAN;
	        } else if (subject.getClass().equals(java.lang.Double.class)) {
	            typeName = TYPE_NAME_NUMERIC;
	        }else if (subject.getClass().equals(java.lang.Long.class)) {
	            typeName = TYPE_NAME_BIGINT;
	        }
        }
        
        if(typeName==null){
        	ps.setArray(i, null);
        }else{
        	// 这3行是关键的代码，创建Array，然后ps.setArray(i, array)就可以了
            Connection conn = ps.getConnection();
            Array array = conn.createArrayOf(typeName, parameter.toArray());
            ps.setArray(i, array);
        }
    }

    @Override
    public List<?> getNullableResult(ResultSet rs, String columnName)
            throws SQLException {

        return getArray(rs.getArray(columnName));
    }

    @Override
    public List<?> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {

        return getArray(rs.getArray(columnIndex));
    }

    @Override
    public List<?> getNullableResult(CallableStatement cs, int columnIndex)
            throws SQLException {

        return getArray(cs.getArray(columnIndex));
    }
    
    public List<?> getArray(Array array) throws SQLException {
    	List<Object> list = new LinkedList<Object>();
        if (array == null) {
            return null;
        }

        Collections.addAll(list, (Object[]) array.getArray());
        
        return list;
    }
}
